在昨天的文章,帶來簡單的錯誤處理運用,今天要帶來較為實務上的運
Go 語言本身沒有例外處理機制,而是以 defer、panic、recover 取而代之,用來滿足錯誤處理的需求。
在 Go 語言中,可以使用 defer 來使某個韓式達到延遲的效果,我們來看一下這個所謂延遲的效果:
package main
import (
"fmt"
)
func main() {
defer fmt.Println(1)
fmt.Println(2)
}
上述的程式碼會先印出2,在印出1,這是就是延遲的效果,在 main function 中,在最後 return 前,執行 defer 後的程式碼。
那如果有多個函式被冠上 defer 呢?我們看下列的程式碼:
package main
import (
"fmt"
)
func main() {
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
}
這樣印出來的順序為3、2、1,所以我們得知,印出的順序跟 defer 的順序相反,也就是第一個 defer,會最後一個執行。
使用 panic 會導致系統崩潰和服務中斷,所以 panic 會使用在發生較重大錯誤的時候,我們這裡稍微將昨天程式更改一下:
package main
import (
"fmt"
"strconv"
)
func main() {
i, err := strconv.Atoi("0.5")
if err != nil {
panic("crash")
fmt.Println("couldn't convert number:", err)
}
fmt.Println("Converted integer:", i)
}
在執行後會產生裡面的錯誤訊息,且不會執行後面的程式碼,來看看他輸出的結果:
panic: crash
其實這個例子只是簡單舉例 panic 的作用,在你自己的服務中,什麼時候要使用到 panic,需要自己評估。
Go 語言中沒有try-catch這類的捕捉語法,但提供 recover 可以捕捉到 panic 拋擲錯誤,以回復系統以避免程序崩潰。因為 defer 在程式碼最後必執行的特性,recover 必須和 defer 配合使用,如下:
package main
import (
"fmt"
"strconv"
)
func main() {
i, err := strconv.Atoi("0.5")
defer func() {
if err := recover(); err != nil {
fmt.Println("couldn't convert number:", err)
}
}()
if err != nil {
panic("crash")
}
fmt.Println("Converted integer:", i)
}
在執行 panic 後系統並無直接崩潰,而是繼續執行 recover 後面的程式碼,但一樣,在 panic 後的程式碼是不會被執行的。
今天介紹 defer、panic、recover 三者的使用方式,而在使用上,需考慮到自己的需求。Go 語言中,使用 error 的話,可以明確地進行錯誤檢查;而使用 panic 會比較便於傳播錯誤,建議搭配 recover 使用以捕捉錯誤,並轉換成 error。